<script lang="ts" setup>
import { ref, defineProps, reactive, getCurrentInstance, onMounted, watch } from 'vue'
import Sortable from 'sortablejs'
const table = ref(null)
const props = defineProps({
    modelValue: { type: Array, default: () => [] },
    addTemplate: { type: Object, default: () => {} },
    placeholder: { type: String, default: '暂无数据' },
    dragSort: { type: Boolean, default: false },
    hideAdd: { type: Boolean, default: false },
    hideDelete: { type: Boolean, default: false }
})
const emits = defineEmits(['delete', 'add', 'edit', 'drag-sort'])
const state = reactive({
    data: []
})
const { proxy } = getCurrentInstance()
onMounted(() => {
    state.data = props.modelValue
    if (props.dragSort) {
        rowDrop()
    }
})

const rowDrop = () => {
    const tbody = proxy.$refs.table.$el.querySelector('.el-table__body-wrapper tbody')
    Sortable.create(tbody, {
        handle: '.move',
        animation: 300,
        ghostClass: 'ghost',
        onEnd({ newIndex, oldIndex }) {
            state.data.splice(newIndex, 0, state.data.splice(oldIndex, 1)[0])
            const newArray = state.data.slice(0)
            const tmpHeight = proxy.$refs.formTable.offsetHeight
            proxy.$refs.formTable.style.setProperty('height', tmpHeight + 'px')
            state.data = []
            proxy.$nextTick(() => {
                state.data = newArray
                proxy.$nextTick(() => {
                    proxy.$refs.formTable.style.removeProperty('height')
                })
            })
        }
    })
}

const rowAdd = () => {
    const temp = JSON.parse(JSON.stringify(props.addTemplate))
    state.data.push(temp)
    emits('add', temp)
}

const rowDel = (row, index) => {
    state.data.splice(index, 1)
    emits('delete', row)
}

const pushRow = (row) => {
    const temp = row || JSON.parse(JSON.stringify(props.addTemplate))
    state.data.push(temp)
    emits('add', temp)
}

const deleteRow = (index) => {
    state.data.splice(index, 1)
    emits('delete', state.data[index])
}

watch(
    () => props.modelValue,
    (value) => {
        state.data = value
    },
    { deep: true }
)
watch(
    () => state.data,
    (value) => {
        proxy.$emit('edit', value)
    },
    { deep: true }
)
</script>

<template>
    <div class="form-table" ref="formTable">
        <el-table :data="state.data" ref="table" border stripe width="100%">
            <el-table-column type="index" width="50" fixed="left">
                <template #header>
                    <el-button
                        v-if="!props.hideAdd"
                        type="primary"
                        size="small"
                        circle
                        @click="rowAdd"
                    >
                        <icon name="el-icon-plus" />
                    </el-button>
                </template>
                <template #default="scope">
                    <div
                        :class="[
                            'form-table-handle',
                            { 'form-table-handle-delete': !props.hideDelete }
                        ]"
                    >
                        <span>{{ scope.$index + 1 }}</span>
                        <el-button
                            v-if="!props.hideDelete"
                            type="danger"
                            size="small"
                            plain
                            circle
                            @click="rowDel(scope.row, scope.$index)"
                            ><icon name="el-icon-delete" />
                        </el-button>
                    </div>
                </template>
            </el-table-column>
            <el-table-column label="" width="50" v-if="props.dragSort">
                <template #default>
                    <div class="move" style="cursor: move">m</div>
                </template>
            </el-table-column>
            <slot></slot>
            <template #empty>
                {{ placeholder }}
            </template>
        </el-table>
    </div>
</template>

<style scoped lang="scss">
.form-table {
    width: 100%;
}
.form-table .form-table-handle {
    text-align: center;
}
.form-table .form-table-handle span {
    display: inline-block;
}
.form-table .form-table-handle button {
    display: none;
}
.form-table .hover-row .form-table-handle-delete span {
    display: none;
}
.form-table .hover-row .form-table-handle-delete button {
    display: inline-block;
}
.form-table .move {
    text-align: center;
    font-size: 14px;
    margin-top: 3px;
}
</style>
